package com.example.index.tools

import android.content.ClipData
import android.content.ClipboardManager
import android.content.Context
import android.content.Intent
import android.content.pm.ApplicationInfo
import android.content.pm.PackageManager
import android.content.res.Resources
import android.graphics.*
import android.graphics.drawable.Drawable
import android.net.Uri
import android.os.*
import android.util.DisplayMetrics
import androidx.appcompat.app.AppCompatActivity
import android.util.Log
import android.view.View
import com.example.index.R
import com.hiray.util.ShareHelper
import es.dmoral.toasty.Toasty
import io.reactivex.Maybe
import io.reactivex.MaybeObserver
import io.reactivex.android.schedulers.AndroidSchedulers
import io.reactivex.disposables.Disposable
import io.reactivex.schedulers.Schedulers
import kotlinx.android.synthetic.main.activity_apk_info_extract.*
import java.io.BufferedOutputStream
import java.io.File
import java.io.FileOutputStream
import java.io.InputStream
import java.util.ArrayList

class ApkInfoExtractActivity : AppCompatActivity() {

    val TAG = "ApkInfoExtractActivity"

    val STABLE_FILE_NAME = "sharePic.png"

    lateinit var APP_PKG_NAME: String

    var extractedAppLogoBitmap: Bitmap? = null

    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContentView(R.layout.activity_apk_info_extract)
        processApkIntentIfMatched(intent)
    }

    private fun processApkIntentIfMatched(intent: Intent?) {
        if (intent != null) {
            if (intent.action == Intent.ACTION_VIEW || intent.action == Intent.ACTION_SEND) {
                val data = intent.extras?.get(Intent.EXTRA_STREAM) as Uri?
                if (data != null) {
                    asyncSaveFile(data)
                }
            }
        }
    }

    private fun asyncSaveFile(data: Uri) {

        Maybe.just(data)
            .map {
                val fileName = resolveFileName(it)
                val file = File(
                    Environment.getExternalStorageDirectory(), fileName
                )
//                val sink = Okio.buffer(Okio.sink(file))
                val stream = contentResolver.openInputStream(data)
                saveFileToDest(stream!!, file)
//                sink.writeAll(Okio.source(stream))

                return@map file
            }
            .subscribeOn(Schedulers.io())
            .observeOn(AndroidSchedulers.mainThread())
            .subscribe(object : MaybeObserver<File> {

                var disposable: Disposable? = null

                override fun onSuccess(t: File) {
                    Log.i(TAG, "onSuccess: $t")
                    extractApkInfo(t)
                }

                override fun onComplete() {
                    if (disposable?.isDisposed != true)
                        disposable?.dispose()
                }

                override fun onSubscribe(d: Disposable) {
                    disposable = d
                }

                override fun onError(e: Throwable) {
                    Log.i(TAG, "onError: ${e.localizedMessage}")
                }

            })

    }


    fun saveFileToDest(ins: InputStream, dest: File) {

        BufferedOutputStream(FileOutputStream(dest)).use { bos ->
            val buffer = ByteArray(2048)
            var len: Int
            while ((ins.read(buffer)).also { len = it } != -1) {
                bos.write(buffer, 0, len)
                bos.flush()
            }

            bos.close()
            ins.close()
        }

    }


    private fun extractApkInfo(t: File) {
        if (t.exists().not())
            return
        val archiveInfo = packageManager.getPackageArchiveInfo(t.absolutePath, 0)

        if (archiveInfo != null) {
            APP_PKG_NAME = archiveInfo.packageName
            archiveInfo.applicationInfo.sourceDir = t.absolutePath
            archiveInfo.applicationInfo.publicSourceDir = t.absolutePath
            var icon: Drawable? = packageManager.getApplicationIcon(archiveInfo.applicationInfo)
            if (icon == null) {
                icon = getIconFromPackageName(APP_PKG_NAME, this)
            }
            extractedAppLogoBitmap = convertDrawable2Bitmap(icon!!)
            iv_app_icon.setImageDrawable(icon)
            tv_app_package_name.text = APP_PKG_NAME.plus("(点我复制包名)")
            tv_app_package_name.setOnClickListener {
                val copyService = getSystemService(Context.CLIPBOARD_SERVICE) as ClipboardManager
                copyService.setPrimaryClip(ClipData.newPlainText("pkgName", APP_PKG_NAME))
                Toasty.info(this@ApkInfoExtractActivity, "已复制包名到剪切板", Toasty.LENGTH_LONG).show()
            }
            extractedAppLogoBitmap?.compress(
                Bitmap.CompressFormat.PNG,
                100,
                FileOutputStream(File(filesDir, STABLE_FILE_NAME), false)
            )

            val destBitmap = Bitmap.createBitmap(144, 144, Bitmap.Config.ARGB_8888)

            val location = IntArray(2) { 0 }
            iv_app_icon.getLocationInWindow(location)

//            PixelCopy.request(
//                window,
//                Rect(location[0], location[1], location[0] + iv_app_icon.width, location[1] + iv_app_icon.height),
//                destBitmap,
//                {
//
//                    iv_thumbnail.setImageBitmap(destBitmap)
//
//                },
//                Handler()
//            )
        }

    }

    private fun getIconFromPackageName(packageName: String, context: Context): Drawable? {
        val pm = context.packageManager
        try {
            val pi = pm.getPackageInfo(packageName, 0)
            val otherAppCtx = context.createPackageContext(
                packageName, Context
                    .CONTEXT_IGNORE_SECURITY
            )
            val displayMetrics = ArrayList<Int>()
            displayMetrics.add(DisplayMetrics.DENSITY_XXXHIGH)
            displayMetrics.add(DisplayMetrics.DENSITY_XXHIGH)
            displayMetrics.add(DisplayMetrics.DENSITY_XHIGH)
            displayMetrics.add(DisplayMetrics.DENSITY_HIGH)
            displayMetrics.add(DisplayMetrics.DENSITY_TV)
            for (displayMetric in displayMetrics) {
                try {
                    val d = otherAppCtx.resources.getDrawableForDensity(
                        pi
                            .applicationInfo.icon, displayMetric
                    )
                    if (d != null) {
                        return d
                    }
                } catch (e: Resources.NotFoundException) {
                    // ignore
                }

            }
        } catch (e: Exception) {
            // Handle Error here
        }

        val appInfo: ApplicationInfo
        try {
            appInfo = pm.getApplicationInfo(packageName, 0)
        } catch (e: PackageManager.NameNotFoundException) {
            return null
        }

        return appInfo.loadIcon(pm)
    }


    private fun convertDrawable2Bitmap(drawable: Drawable): Bitmap {

        val w = drawable.intrinsicWidth
        val h = drawable.intrinsicHeight

        // 取 drawable 的颜色格式
        val config = if (drawable.opacity != PixelFormat.OPAQUE) Bitmap.Config.ARGB_8888
        else Bitmap.Config.RGB_565
        // 建立对应 bitmap
        val bitmap = Bitmap.createBitmap(w, h, config)
        // 建立对应 bitmap 的画布
        val canvas = Canvas(bitmap);
        drawable.setBounds(0, 0, w, h)
        // 把 drawable 内容画到画布中
        drawable.draw(canvas)
        return bitmap
    }

    private fun resolveFileName(data: Uri): String {

        return "testExtractor.apk"
    }


    override fun onNewIntent(intent: Intent?) {
        super.onNewIntent(intent)
        processApkIntentIfMatched(intent)
    }


    fun sendToQQ(view: View) {
        ShareHelper.shareToTimOrQQ(this, File(filesDir, STABLE_FILE_NAME), pkgName = APP_PKG_NAME)
    }
}
